import Phaser from 'phaser';

type Palette = { hair?: string; cloth?: string; skin?: string; };

export interface SpritesCollection {
  player: {
    baseSize: number;
    scale: number;
    frames: {
      idle: string[];
      walk: string[];
      attack: string[];
      dash: string[];
    };
  };
  enemy: {
    slime: string;
    bat: string;
  };
  icons: {
    atk: string;
    fireball: string;
    dash: string;
    heal: string;
  };
}

/**
 * 生成像素精灵（基于离屏 Canvas），并通过 scene.textures.addCanvas 注册为纹理。
 * 返回纹理键集合（用于 GameScene 中创建精灵 / 动画）。
 */
export default function generateSprites(scene: Phaser.Scene, palette?: Palette): SpritesCollection {
  const P: Palette = Object.assign({ hair: '#f97316', cloth: '#7c3aed', skin: '#ffd8b3' }, palette || {});
  const base = 16;
  const iconSize = 16;

  const out: SpritesCollection = {
    player: {
      baseSize: base,
      scale: 2,
      frames: { idle: [], walk: [], attack: [], dash: [] }
    },
    enemy: { slime: '', bat: '' },
    icons: { atk: '', fireball: '', dash: '', heal: '' }
  };

  function mk(w = base, h = base): HTMLCanvasElement {
    const c = document.createElement('canvas');
    c.width = w;
    c.height = h;
    return c;
  }

  function shade(hex: string, percent: number): string {
    const v = hex.substring(1);
    const r = parseInt(v.substr(0, 2), 16);
    const g = parseInt(v.substr(2, 2), 16);
    const b = parseInt(v.substr(4, 2), 16);
    const f = (n: number) => Math.max(0, Math.min(255, Math.round(n + (percent / 100) * 255)));
    const hr = f(r).toString(16).padStart(2, '0');
    const hg = f(g).toString(16).padStart(2, '0');
    const hb = f(b).toString(16).padStart(2, '0');
    return `#${hr}${hg}${hb}`;
  }

  function drawPlayerLow(ctx: CanvasRenderingContext2D, variant = 'idle', frame = 0) {
    ctx.clearRect(0, 0, base, base);
    const hair = P.hair as string;
    const cloth = P.cloth as string;
    const skin = P.skin as string;
    const darkHair = shade(hair, -18);
    const darkCloth = shade(cloth, -18);

    // head/hair
    ctx.fillStyle = hair; ctx.fillRect(4, 0, 8, 3);
    ctx.fillRect(3, 2, 2, 3); ctx.fillRect(11, 2, 2, 3);
    // face
    ctx.fillStyle = skin; ctx.fillRect(5, 3, 6, 4);
    // eyes
    ctx.fillStyle = '#111'; ctx.fillRect(6, 4, 1, 1); ctx.fillRect(9, 4, 1, 1);
    // neck
    ctx.fillStyle = skin; ctx.fillRect(7, 7, 2, 1);
    // body
    ctx.fillStyle = cloth; ctx.fillRect(4, 8, 8, 5);
    // collar/highlight
    ctx.fillStyle = darkCloth; ctx.fillRect(4, 8, 8, 1);

    // arms animation offset for walk
    const armOffset = (variant === 'walk') ? ((frame % 2 === 0) ? -1 : 1) : 0;
    ctx.fillStyle = cloth;
    ctx.fillRect(2, 9 + (armOffset > 0 ? 1 : 0), 2, 3);
    ctx.fillRect(12, 9 - (armOffset > 0 ? 1 : 0), 2, 3);

    // legs & boots - walking frames move
    let leftLegY = 13; let rightLegY = 13;
    if (variant === 'walk') {
      if (frame % 4 === 0) { leftLegY = 12; rightLegY = 14; }
      if (frame % 4 === 1) { leftLegY = 13; rightLegY = 13; }
      if (frame % 4 === 2) { leftLegY = 14; rightLegY = 12; }
      if (frame % 4 === 3) { leftLegY = 13; rightLegY = 13; }
    }
    ctx.fillStyle = '#1f2937';
    ctx.fillRect(5, leftLegY, 2, 2);
    ctx.fillRect(9, rightLegY, 2, 2);

    // small belt highlight
    ctx.fillStyle = '#ffd580';
    ctx.fillRect(7, 10, 2, 1);

    // soft outline shadow
    ctx.fillStyle = '#000000';
    ctx.globalAlpha = 0.18;
    ctx.fillRect(4, 8, 8, 5);
    ctx.globalAlpha = 1;
  }

  // build player frames
  for (let f = 0; f < 2; f++) {
    const c = mk(base, base);
    const ctx = c.getContext('2d')!;
    ctx.imageSmoothingEnabled = false;
    drawPlayerLow(ctx, 'idle', f);
    const key = `player_idle_${f}`;
    scene.textures.addCanvas(key, c);
    out.player.frames.idle.push(key);
  }

  for (let f = 0; f < 4; f++) {
    const c = mk(base, base);
    const ctx = c.getContext('2d')!;
    ctx.imageSmoothingEnabled = false;
    drawPlayerLow(ctx, 'walk', f);
    const key = `player_walk_${f}`;
    scene.textures.addCanvas(key, c);
    out.player.frames.walk.push(key);
  }

  for (let f = 0; f < 3; f++) {
    const c = mk(base, base);
    const ctx = c.getContext('2d')!;
    ctx.imageSmoothingEnabled = false;
    drawPlayerLow(ctx, 'idle', 0);
    // add sword forward
    ctx.fillStyle = '#fff';
    if (f === 0) ctx.fillRect(11, 7, 2, 1);
    if (f === 1) { ctx.fillRect(11, 6, 3, 1); ctx.fillRect(12, 7, 1, 1); }
    if (f === 2) { ctx.fillRect(11, 5, 4, 1); ctx.fillRect(13, 6, 1, 1); }
    const key = `player_attack_${f}`;
    scene.textures.addCanvas(key, c);
    out.player.frames.attack.push(key);
  }

  for (let f = 0; f < 2; f++) {
    const c = mk(base, base);
    const ctx = c.getContext('2d')!;
    ctx.imageSmoothingEnabled = false;
    drawPlayerLow(ctx, 'idle', 0);
    // lean: hair recolor highlight
    ctx.fillStyle = shade(P.hair as string, -8);
    ctx.fillRect(4, 0, 8, 3);
    const key = `player_dash_${f}`;
    scene.textures.addCanvas(key, c);
    out.player.frames.dash.push(key);
  }

  // enemies
  const slime = mk(base, base);
  const sg = slime.getContext('2d')!;
  sg.imageSmoothingEnabled = false;
  sg.fillStyle = '#34d399';
  sg.fillRect(4, 6, 8, 6);
  sg.fillRect(5, 5, 6, 1);
  sg.fillStyle = shade('#34d399', -14);
  sg.fillRect(4, 6, 8, 1);
  sg.fillStyle = '#08111a';
  sg.fillRect(6, 8, 1, 1);
  sg.fillRect(9, 8, 1, 1);
  scene.textures.addCanvas('enemy_slime', slime);
  out.enemy.slime = 'enemy_slime';

  const bat = mk(base, base);
  const bg = bat.getContext('2d')!;
  bg.imageSmoothingEnabled = false;
  bg.fillStyle = '#f97316';
  bg.fillRect(6, 5, 4, 3);
  bg.fillRect(2, 7, 3, 1);
  bg.fillRect(11, 7, 3, 1);
  bg.fillRect(3, 8, 2, 1);
  bg.fillRect(12, 8, 2, 1);
  bg.fillStyle = '#000';
  bg.fillRect(7, 6, 1, 1);
  bg.fillRect(8, 6, 1, 1);
  scene.textures.addCanvas('enemy_bat', bat);
  out.enemy.bat = 'enemy_bat';

  // icons
  function iconSlash() {
    const c = mk(iconSize, iconSize);
    const g = c.getContext('2d')!;
    g.imageSmoothingEnabled = false;
    g.fillStyle = '#ffd1d1';
    g.fillRect(3, 2, 2, 8);
    g.fillStyle = '#fff1a8';
    g.fillRect(5, 3, 2, 6);
    g.fillStyle = '#fb7185';
    g.fillRect(7, 5, 3, 2);
    return c;
  }
  function iconFire() {
    const c = mk(iconSize, iconSize);
    const g = c.getContext('2d')!;
    g.imageSmoothingEnabled = false;
    g.fillStyle = '#ffb86b'; g.fillRect(6, 2, 4, 4);
    g.fillStyle = '#fb7185'; g.fillRect(5, 4, 6, 3);
    g.fillStyle = '#fff5d6'; g.fillRect(7, 3, 2, 2);
    return c;
  }
  function iconDash() {
    const c = mk(iconSize, iconSize);
    const g = c.getContext('2d')!;
    g.imageSmoothingEnabled = false;
    g.fillStyle = '#93c5fd'; g.fillRect(3, 5, 10, 3);
    g.fillStyle = '#60a5fa'; g.fillRect(9, 4, 2, 1);
    g.fillStyle = '#fff'; g.fillRect(4, 6, 4, 1);
    return c;
  }
  function iconHeal() {
    const c = mk(iconSize, iconSize);
    const g = c.getContext('2d')!;
    g.imageSmoothingEnabled = false;
    g.fillStyle = '#a5b4fc'; g.fillRect(5, 2, 6, 6);
    g.fillStyle = '#fff'; g.fillRect(7, 4, 2, 1);
    g.fillRect(7, 3, 1, 4);
    return c;
  }

  scene.textures.addCanvas('icon_atk', iconSlash());
  scene.textures.addCanvas('icon_fireball', iconFire());
  scene.textures.addCanvas('icon_dash', iconDash());
  scene.textures.addCanvas('icon_heal', iconHeal());

  out.icons.atk = 'icon_atk';
  out.icons.fireball = 'icon_fireball';
  out.icons.dash = 'icon_dash';
  out.icons.heal = 'icon_heal';

  return out;
}
